package com.xtpt.disaster.controller;

import com.alibaba.fastjson.JSON;
import com.xtpt.disaster.bean.*;
import com.xtpt.disaster.common.PortalResult;
import com.xtpt.disaster.common.PropertyConfig;
import com.xtpt.disaster.common.consts.*;
import com.xtpt.disaster.service.*;
import com.xtpt.disaster.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.sql.Time;
import java.text.DateFormat;
import java.util.*;


import static com.xtpt.disaster.common.consts.UrlConst.QUARTZ_ADD;
import static com.xtpt.disaster.common.consts.UrlConst.QUARTZ_IP;

@CrossOrigin
@ComponentScan("com.example.spring")
@RestController
@RequestMapping("/db")
@Api(tags = "MYSQL数据库备份恢复")
public class DBMysqlController {
    @Autowired
    TaskInfoManageService taskInfoManageService;

    @Autowired
    DBMysqlJobDetailService dbMysqlJobDetailService;

    @Autowired
    DBNodeInfoService dbNodeInfoService;

    @Autowired
    ServerPathUtil serverPathUtil;

    @Autowired
    PropertyConfig propertyConfig;


    @PostMapping("/receive")
    public PortalResult getReceive(@RequestBody ClientCmdExecResult result) {
        System.out.println(result);

        return PortalResult.ok();
    }

    @GetMapping("/getalljob")
    @ApiOperation(value = "获取所有的job")
    public PortalResult getAllJob() {
        List<JobDetail> allJobDetails = dbMysqlJobDetailService.selectAllJobDetail();
        if(allJobDetails != null) {
            return PortalResult.ok(allJobDetails);
        } else {
            return PortalResult.error("获取所有作业失败");
        }
    }


    @GetMapping("/getjobbyid")
    @ApiOperation(value = "根据id获取job详情")
    public PortalResult getJobById(@RequestParam(value = "id") Long id) {
        JobDetail jobDetail = dbMysqlJobDetailService.selectByPrimaryKey(id);
        if (jobDetail != null) {
            return PortalResult.ok(jobDetail);
        } else {
            return PortalResult.error("获取作业失败");
        }
    }

    @PostMapping("/getjobsbycon")
    @ApiOperation(value = "根据id获取job详情")
    public PortalResult getJobsByConn(@RequestBody JobDetail conJobDetail) {

        List<JobDetail> jobDetails = dbMysqlJobDetailService.selectJobByCon(conJobDetail);
        if (jobDetails != null) {
            return PortalResult.ok(jobDetails);
        } else {
            return PortalResult.error("未查询到符合条件的任务");
        }
    }

    @GetMapping("/deletebyid")
    @ApiOperation(value = "根据id删除任务")
    public PortalResult deleteById(@RequestParam(value = "id") Long id) {
        int count = taskInfoManageService.deleteById(id);

        if (count == 1) {
            return PortalResult.ok(count);
        } else {
            return PortalResult.error("删除失败");
        }
    }

    @PostMapping("/batchdelete")
    @ApiOperation(value = "批量删除节点")
    public PortalResult batchDelete(@RequestBody long[] ids) {
        int count = taskInfoManageService.deleteBatch(ids);
        if (count >= 1) {
            return PortalResult.ok(count);
        } else {
            return PortalResult.error("批量删除失败");
        }
    }

    @GetMapping("/getbyid")
    @ApiOperation("根据id获取任务详情")
    public PortalResult getById(@RequestParam(value = "id") Long id) {
        TaskInfo taskInfo = taskInfoManageService.selectTaskInfoById(id);
        if(taskInfo != null) {
            return PortalResult.ok(taskInfo);
        } else {
            return PortalResult.error("查询失败");
        }
    }

    @GetMapping("/getall")
    @ApiOperation(value = "获取所有的任务")
    public PortalResult getAll() {
        List<TaskInfo> allTaskInfo = taskInfoManageService.getAllTaskInfo();
        if(allTaskInfo != null) {
            return PortalResult.ok(allTaskInfo);
        } else {
            return PortalResult.error("查询所有信息失败");
        }
    }
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskName", value = "任务名称", type = "String"),
            @ApiImplicitParam(name = "taskDesc", value = "任务描述", type = "String"),
            @ApiImplicitParam(name = "taskStarttime", value = "周期任务开始时间", type = "String"),
            @ApiImplicitParam(name = "taskEndtime", value = "周期任务结束时间, 即时任务和定时任务不需要展示也不需要传值，周期任务需要展示，选择一个日期或者无限，表示一直按周期备份，没有停止时间", type = "String"),
            @ApiImplicitParam(name = "taskStatus", value = "任务状态, 暂时不填写", type = "Integer"),
            @ApiImplicitParam(name = "taskType", value = "任务类型，", type = "Integer"),
            @ApiImplicitParam(name = "taskFileType", value = "文件类型", type = "Integer"),
            @ApiImplicitParam(name = "taskExecType", value = "任务执行类型， 立刻执行任务 0 在指定时间执行一次 1 日、周、月、年周期性执行", type = "Integer"),
            @ApiImplicitParam(name = "taskUnit", value = "周期单位, 日 0 周 1 月 2 年 3", type = "Integer"),
            @ApiImplicitParam(name = "taskUnitCount", value = "周期间隔 周期备份的间隔时间", type = "Integer"),
            @ApiImplicitParam(name = "dbId", value = "数据库id", type = "Integer"),
            @ApiImplicitParam(name = "nodeId", value = "节点id(数据库不需要此参数，文件备份时需要)", type = "Integer"),
            @ApiImplicitParam(name = "taskClientPath", value = "备份文件路径(数据库备份不需要此参数，文件备份时需要)", type = "String"),
            @ApiImplicitParam(name = "createTime", value = "创建时间", type = "Date"),
            @ApiImplicitParam(name = "updateTime", value = "修改时间", type = "Date"),
    })
    @PostMapping("/submit")
    @ApiOperation(value = "前端提交接口")
    public PortalResult submit(@RequestBody TaskInfo taskInfo) throws IOException, InterruptedException {
        QuartzEntity quartzEntity = new QuartzEntity();
        Long longid = IDGenerator.longid();
        quartzEntity.setJobName(longid.toString());
        quartzEntity.setOldJobName(taskInfo.getOldJobName());
        quartzEntity.setJobGroup(taskInfo.getTaskName());
        quartzEntity.setDescription(taskInfo.getTaskDesc());
        quartzEntity.setScheduleType(ScheduleTypeEnum.getObject(taskInfo.getTaskExectype()));
        quartzEntity.setIntervalType(IntervalTypeEnum.getObject(taskInfo.getTaskUnit()));
        quartzEntity.setTaskUnitCount(taskInfo.getTaskUnitCount());
        quartzEntity.setStartAt(taskInfo.getTaskStarttime());
        quartzEntity.setEndAt(taskInfo.getTaskEndtime());
        quartzEntity.setScheduleType(ScheduleTypeEnum.getObject(taskInfo.getTaskExectype()));
        String taskPath = "";
        if ( taskInfo.getTaskType() == TaskTypeEnum.BACKUP.getValue()) {
            taskPath = serverPathUtil.generateCallbackUrl("/db/backup");
        } else if (taskInfo.getTaskType() == TaskTypeEnum.RECOVER.getValue()) {
            taskPath = serverPathUtil.generateCallbackUrl("/db/recover");
        }
        ActionParameters actionParameters = new ActionParameters();
        actionParameters.setRequestUrl(taskPath);
        actionParameters.setRequestMethod("POST");
        taskInfo.setTaskId(longid);
        actionParameters.setRequestParameters(taskInfo);
        quartzEntity.setActionParameters(actionParameters);
        String s = JSON.toJSONString(quartzEntity);

        int count = taskInfoManageService.insertOneTaskInfo(taskInfo);
        if (count != 1) {
            return PortalResult.error("插入数据库不成功，新建任务失败");
        }

        String path = "http://" + propertyConfig.getQutarz_server_ip() + ":" + propertyConfig.getQuartzServerPort() + propertyConfig.getQuartz_add();
        String p = cn.hutool.http.HttpUtil.post(path, s);
        System.out.println(p);
        PortalResult portalResult = JSON.parseObject(p, PortalResult.class);
        System.out.println(portalResult);

        if(portalResult.getStatus() == StatusConst.SUCCESS) {
                return PortalResult.ok();
        } else {
            taskInfo.setTaskStatus(StatusConst.ERROR);
            taskInfoManageService.updateTaskInfoById(taskInfo);
            return PortalResult.error("创建任务计划失败");
        }
    }


    @PostMapping("/updatetask")
    @ApiOperation(value = "更改task")
    public PortalResult update(@RequestBody TaskInfo taskInfo) throws IOException, InterruptedException {
        System.out.println(taskInfo.getTaskId());
        QuartzEntity quartzEntity = new QuartzEntity();
        quartzEntity.setJobName(taskInfo.getTaskId().toString());
        quartzEntity.setOldJobName(taskInfo.getTaskId().toString());
        quartzEntity.setJobGroup(taskInfo.getTaskName());
        quartzEntity.setOldJobGroup(taskInfo.getTaskName());
        quartzEntity.setDescription(taskInfo.getTaskDesc());
        quartzEntity.setScheduleType(ScheduleTypeEnum.getObject(taskInfo.getTaskExectype()));
        quartzEntity.setIntervalType(IntervalTypeEnum.getObject(taskInfo.getTaskUnit()));
        quartzEntity.setTaskUnitCount(taskInfo.getTaskUnitCount());
        quartzEntity.setStartAt(taskInfo.getTaskStarttime());
        quartzEntity.setEndAt(taskInfo.getTaskEndtime());
        quartzEntity.setScheduleType(ScheduleTypeEnum.getObject(taskInfo.getTaskExectype()));
        String taskPath = "";
        if ( taskInfo.getTaskType() == TaskTypeEnum.BACKUP.getValue()) {
            taskPath = serverPathUtil.generateCallbackUrl("/db/backup");
        } else if (taskInfo.getTaskType() == TaskTypeEnum.RECOVER.getValue()) {
            taskPath = serverPathUtil.generateCallbackUrl("/db/recover");
        }
        ActionParameters actionParameters = new ActionParameters();
        actionParameters.setRequestUrl(taskPath);
        actionParameters.setRequestMethod("POST");
        actionParameters.setRequestParameters(taskInfo);
        quartzEntity.setActionParameters(actionParameters);
        String s = JSON.toJSONString(quartzEntity);
        String path = "http://" + propertyConfig.getQutarz_server_ip() + ":" + propertyConfig.getQuartzServerPort() + propertyConfig.getQuartz_add();
        String p = cn.hutool.http.HttpUtil.post(path, s);
        PortalResult portalResult = JSON.parseObject(p, PortalResult.class);

        if(portalResult.getStatus() == StatusConst.SUCCESS) {
            int count = taskInfoManageService.updateTaskInfoById(taskInfo);
            if (count == 1) {
                return PortalResult.ok();
            } else {
                return PortalResult.error("修改任务失败");
            }
        } else {
            return portalResult;
        }
    }

    @PostMapping("/backup")
    @ApiOperation(value = "MYSQL备份接口")
    public PortalResult backup(@RequestBody TaskInfo taskInfo) throws IOException, InterruptedException {
        JobDetail jobDetail = new JobDetail();
        jobDetail.setJobType(taskInfo.getTaskType());
        jobDetail.setJobDesc(taskInfo.getTaskDesc());
        jobDetail.setDbId(taskInfo.getDbId());
        jobDetail.setJobName(taskInfo.getTaskName());
        jobDetail.setTaskId(taskInfo.getTaskId());
        jobDetail.setDataType(taskInfo.getTaskFileType());
        Long jobId = IDGenerator.longid();
        jobDetail.setJobId(jobId);
        DbnodeInfo dbNodeInfo = dbNodeInfoService.selectByPrimaryKey(taskInfo.getDbId());
        String startTimeStr = TimeUtil.dateMakerString();
        Date startTime = TimeUtil.dateMaker();
        String host = dbNodeInfo.getNodeIp();
        String username = dbNodeInfo.getNodeDbUsername();
        String password = dbNodeInfo.getNodeDbPassword();
        String backupDBName = dbNodeInfo.getNodeDbName();
        String serverPath = serverPathUtil.getDBServerPath(taskInfo.getTaskId().toString(), backupDBName, taskInfo.getTaskType(), "0");
        System.out.println(serverPath);
        String backupName = backupDBName + "_" + startTimeStr;
        String binPath = dbNodeInfo.getNodeDbBinPath();
        int backupRes = DatabaseUtil.entirelyBackup(binPath, host, username, password, backupDBName, serverPath, backupName);
        if (backupRes == 0) {
            Date endTime = TimeUtil.dateMaker();
            jobDetail.setJobStartTime(startTime);
            jobDetail.setJobEndTime(endTime);
            jobDetail.setSourceDbType(dbNodeInfo.getNodeDbType());
            jobDetail.setServerPath(serverPath + "/" + backupName);
            jobDetail.setScheduleType(taskInfo.getTaskExectype());
            jobDetail.setJobStatus(StatusConst.SUCCESS);
            return dbMysqlJobDetailService.insertSelective(jobDetail);
        } else {
            Date endTime = TimeUtil.dateMaker();
            jobDetail.setJobStartTime(startTime);
            jobDetail.setJobEndTime(endTime);
            jobDetail.setSourceDbType(dbNodeInfo.getNodeDbType());
            jobDetail.setServerPath(serverPath + "/" + backupName);
            jobDetail.setScheduleType(taskInfo.getTaskExectype());
            jobDetail.setJobStatus(StatusConst.ERROR);
            dbMysqlJobDetailService.insertSelective(jobDetail);
            return PortalResult.error("数据库备份出错");
        }
    }

    @PostMapping("/recover")
    @ApiOperation("MYSQL恢复接口")
    public PortalResult recover(@RequestBody TaskInfo taskInfo) throws IOException, InterruptedException {
        JobDetail backupJobDetail = dbMysqlJobDetailService.selectByPrimaryKey(taskInfo.getJobDetailId());
        Long recoverJobId = IDGenerator.longid();
        JobDetail recoverJobDetail = new JobDetail();
        recoverJobDetail.setJobName(taskInfo.getTaskName());
        recoverJobDetail.setJobDesc(taskInfo.getTaskDesc());
        recoverJobDetail.setJobId(recoverJobId);
        recoverJobDetail.setDbId(taskInfo.getDbId());
        recoverJobDetail.setTaskId(taskInfo.getTaskId());
        Long backupTaskId =  backupJobDetail.getTaskId();
        TaskInfo backupTaskInfo = taskInfoManageService.selectTaskInfoById(backupTaskId);
        DbnodeInfo dbNodeInfo = dbNodeInfoService.selectByPrimaryKey(backupTaskInfo.getDbId());
        String host = dbNodeInfo.getNodeIp();
        String username = dbNodeInfo.getNodeDbUsername();
        String password = dbNodeInfo.getNodeDbPassword();
        String backupDBName = dbNodeInfo.getNodeDbName();

        String serverPath = backupJobDetail.getServerPath();
        int i = serverPath.lastIndexOf("/");
        String serverPathDir = serverPath.substring(0,i);
        String fileName = serverPath.substring(i+1);
        Date startTime = TimeUtil.dateMaker();
        String binPath = dbNodeInfo.getNodeDbBinPath();
        int recoverRes = DatabaseUtil.recover(binPath, host, username, password, backupDBName, serverPathDir, fileName);
        if(recoverRes == 0) {
        Date endTime = TimeUtil.dateMaker();
        recoverJobDetail.setJobName(taskInfo.getTaskName());
        recoverJobDetail.setJobStartTime(startTime);
        recoverJobDetail.setJobEndTime(endTime);
        recoverJobDetail.setSourceDbType(dbNodeInfo.getNodeDbType());
        recoverJobDetail.setJobStatus(0);
        recoverJobDetail.setJobType(1);
        recoverJobDetail.setDataType(0);
        return dbMysqlJobDetailService.insertSelective(recoverJobDetail);
        } else {
            Date endTime = TimeUtil.dateMaker();
            recoverJobDetail.setJobName(taskInfo.getTaskName());
            recoverJobDetail.setJobStartTime(startTime);
            recoverJobDetail.setJobEndTime(endTime);
            recoverJobDetail.setSourceDbType(dbNodeInfo.getNodeDbType());
            recoverJobDetail.setJobStatus(0);
            recoverJobDetail.setJobType(1);
            recoverJobDetail.setDataType(0);
            recoverJobDetail.setJobStatus(StatusConst.ERROR);
            // setJobResult 失败原因
            recoverJobDetail.setJobResult(String.valueOf(recoverRes));
            dbMysqlJobDetailService.insertSelective(recoverJobDetail);
            return PortalResult.error("恢复出错");
        }
    }
    }
